package org.jwt.oauth.tools;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;

import org.jwt.oauth.constant.ConstantAttribute;
import org.jwt.oauth.properties.FusionTokenProperties;
import org.springframework.boot.autoconfigure.web.ServerProperties;

public class FusionCheckUrlTools {

	@SuppressWarnings("unchecked")
	public static boolean checkUrl(String url, FusionTokenProperties tokenProperties, HttpServletRequest request) {
		List<String> arrayList = new ArrayList<String>();
		ServletContext servletContext = request.getServletContext();
		Object attribute = servletContext.getAttribute(ConstantAttribute.NOT_AUTH_URL_LIST);
		if (attribute != null) {
			arrayList = (List<String>) servletContext.getAttribute(ConstantAttribute.NOT_AUTH_URL_LIST);
		}else {
			arrayList.add(tokenProperties.getUserLoginUrl());
			arrayList.add(tokenProperties.getLoginErrorUrl());
			arrayList.add(tokenProperties.getDefaultExithUrl());
			arrayList.add(tokenProperties.getDefaultLoginUrl());
			arrayList.add(tokenProperties.getDefaultRefreshUrl());
			String[] split = tokenProperties.getNoRelease();
			if (split != null && split.length > 0) {
				arrayList.addAll(Arrays.asList(split));
			}
			List<String> notAuthUrlList = (List<String>) ConcurrentTools.getConcurrentHashMap().get(ConstantAttribute.NOT_AUTH_URL_LIST);
			if (notAuthUrlList != null && notAuthUrlList.size() > 0) {
				arrayList.addAll(notAuthUrlList);
			}
			servletContext.setAttribute(ConstantAttribute.NOT_AUTH_URL_LIST, arrayList);
		}
		ServerProperties serverProperties = SpringBeanTool.getBean(ServerProperties.class);
		String contextPath = serverProperties.getServlet().getContextPath();
		if (contextPath != null && contextPath.length() > 0) {
			url = url.replaceAll(contextPath, "");
		}
		if (url != null && url.length() > 0 && arrayList.contains(url)) {
			return true;
		}

		if (url != null && url.length() > 0 && checkUrl(url, arrayList)) {
			return true;
		}
		return false;
	}

	public static boolean checkUrl(String url, List<String> pathList) {
		if (pathList != null && pathList.size() > 0 && url != null) {
			for (String path : pathList) {
				if (url!=null && path!=null && matches(url, path)) {
					return true;
				}
			}
		}
		return false;
	}

	public static boolean matches(String source, String regex) {
		if (source.equals(regex) && source.indexOf('\\') < 0) {
			return true;
		}
		int rIdx = 0, sIdx = 0;// 同时遍历源字符串与匹配表达式
		while (rIdx < regex.length() && sIdx < source.length()) {
			char c = regex.charAt(rIdx);// 以匹配表达式为主导
			switch (c) {
			case '*':// 匹配到*号进入下一层递归
				String tempSource = source.substring(sIdx);// 去除前面已经完全匹配的前缀
				String tempRegex = regex.substring(rIdx + 1);// 从星号后一位开始认为是新的匹配表达式
				for (int j = 0; j <= tempSource.length(); j++) {// 此处等号不能缺，如（ABCD，*），等号能达成("", *)条件
					if (matches(tempSource.substring(j), tempRegex)) {// 很普通的递归思路
						return true;
					}
				}
				return false;// 排除所有潜在可能性，则返回false
			case '?':
				break;
			case '\\':// 匹配到反斜杠跳过一位，匹配下一个字符串
				c = regex.charAt(++rIdx);
			default:
				if (source.charAt(sIdx) != c)
					return false;// 普通字符的匹配
			}
			rIdx++;
			sIdx++;
		}
		// 最终source被匹配完全，而regex也被匹配完整或只剩一个*号
		return source.length() == sIdx
				&& (regex.length() == rIdx || regex.length() == rIdx + 1 && regex.charAt(rIdx) == '*');
	}

}
